package in.srain.cube.util.log;

import android.text.TextUtils;

public final class LogMessage {
    private static final byte[] sPoolSync = new byte[0];
    private static final int MAX_POOL_SIZE = 50;
    private static LogMessage sPoolHeader;
    private static int sPoolSize = 0;
    private static ThreadLocal<String> mThreadLocal = new ThreadLocal<>();
    private long mTime;
    private String mTid;
    private String mMessage;
    private Object mMessageData;
    private LogMessage mNext;

    private LogMessage(String tid, String message, Object dataMessage) {
        mTime = System.currentTimeMillis();
        mTid = tid;
        mMessage = message;
        mMessageData = dataMessage;
    }

    public static LogMessage obtain(String message, Object messageData) {

        String tid = getTidForCurrentThread();

        synchronized (sPoolSync) {
            if (sPoolHeader != null) {
                LogMessage m = sPoolHeader;

                sPoolHeader = m.mNext;
                m.mNext = null;
                sPoolSize--;

                m.mTime = System.currentTimeMillis();
                m.mMessage = message;
                m.mMessageData = messageData;
                m.mTid = tid;
                return m;
            }
        }
        return new LogMessage(tid, message, messageData);
    }

    private static String getTidForCurrentThread() {
        String tid = mThreadLocal.get();
        if (TextUtils.isEmpty(tid)) {
            tid = String.valueOf(android.os.Process.myTid());
            mThreadLocal.set(tid);
        }
        return tid;
    }

    public long getTime() {
        return mTime;
    }

    public String getTid() {
        return mTid;
    }

    public String getMessage() {
        return mMessage;
    }

    public Object getMessageData() {
        return mMessageData;
    }

    public void recycle() {
        mTime = 0;
        mTid = null;
        mMessage = null;
        mMessageData = null;
        synchronized (sPoolSync) {
            if (sPoolSize < MAX_POOL_SIZE) {
                mNext = sPoolHeader;
                sPoolHeader = this;
                sPoolSize++;
            }
        }
    }
}
